package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

var mu sync.Mutex //互踩锁
var num int = 0

/*
 *	Goroutines
 *	Go 中的并发执行单位(协程)，类似于轻量级的线程，它与其他协程共享内存并通过通道Channel进行通信
 *	Goroutine 的调度由 Go 运行时管理，用户无需手动分配线程
 *	使用 go 关键字启动 Goroutine
 *	Goroutine 是非阻塞的，可以高效地运行成千上万个 Goroutine
 *	Scheduler
 *	Go 的调度器基于 GMP 模型，调度器会将 Goroutine 分配到系统线程中执行，并通过 M 和 P 的配合高效管理并发
 *	G：Goroutine
 *	M：系统线程（Machine）
 *	P：逻辑处理器（Processor）
 */

func Concurrency1() {
	for i := 0; i < 10; i++ {
		fmt.Println("Go 轻量级线程")
		time.Sleep(2 * time.Second)
	}

}

/*
 *	Channel
	Go 中用于在 Goroutine 之间通信的机制
	支持同步和数据共享，避免了显式的锁机制
	使用 chan 关键字创建，通过 <- 操作符发送和接收数据
	方法中声明的通道参数的规则: varName chan type  表示变量名 通道类型  通道传递和接收的数据类型
*/

func ConcurrencyChannel(channel chan int) {
	var sum int
	for i := 0; i < 10; i++ {
		sum = sum + rand.Intn(10)
	}
	//将求和传递给通道
	channel <- sum //通过通道发送消息
}

// 缓冲区通道
func BufferedChannel(channel chan int) {
	var sum int
	for i := 0; i < 10; i++ {
		sum = sum + rand.Intn(10)
	}
	//将求和传递给通道
	channel <- sum //通过通道发送消息
}

func lockConcurrency(wg *sync.WaitGroup, i int) {
	//上锁
	mu.Lock()
	num = num + i
	fmt.Printf("第%d个协程执行结果:%d\n", i, num)
	//释放锁
	mu.Unlock()
	/*
	 * 在携程执行结束的位置使用 表示一个携程执行结束，计数器也会相应减少
	 */
	wg.Done()
}
